package com.qf.shop.aop;

import com.qf.shop.annotation.ProcessInfo;
import com.qf.shop.entity.ProcessLog;
import com.qf.shop.mapper.ProcessLogMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;

/**
 * https://blog.csdn.net/ilovewqf/article/details/103198763
 * https://blog.csdn.net/baidu_32492845/article/details/79712141
 * @Component 用于定义一些中性化的组件
 * 处理用户的操作日志
 */
@Component
@Aspect
public class ProcessAdvisor{

    private ProcessLogMapper processLogMapper;

    public ProcessAdvisor(ProcessLogMapper processLogMapper) {
        this.processLogMapper = processLogMapper;
    }

    /**
     * 所有的加了 @ProcessInfo 这个注解的方法都会被通知到
     * @param pjp
     * @return
     */
    @Around("@annotation(com.qf.shop.annotation.ProcessInfo)")
    public Object round(ProceedingJoinPoint pjp) {

        MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
        // 获取调用的目标方法的方法名
        String methodName = methodSignature.getName();
        // 获取反射对应的方法
        Method method = methodSignature.getMethod();

        // method.getDeclaringClass().getName() 拿到方法对应的全类名
        String classInfo = method.getDeclaringClass().getName(); // 获取全类名

        // 获取方法头顶的 @ProcessInfo 注解
        ProcessInfo processInfoAnnotation = method.getDeclaredAnnotation(ProcessInfo.class);
        // 获取到 @ProcessInfo 中的内容
        String processInfo = processInfoAnnotation.value();

        // 获取方法的参数信息, 目的是获取参数名
        Parameter[] parameters = method.getParameters(); // 获取方法的参数

        StringBuffer paramString = new StringBuffer();
        // 因为有些方法是没有参数的


        ProcessLog processLog = new ProcessLog();


        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = attr.getRequest().getSession(true);
        String user = (String) session.getAttribute("user");

        processLog.setUserName(user);
        processLog.setCreateTime(new Date());
        processLog.setClassName(classInfo);
        processLog.setMethodName(methodName);
        processLog.setProcessInfo(processInfo);
        processLog.setParamsInfo(paramString.toString());

        processLogMapper.insertProcess(processLog);

        Object obj = null;

        try {
            obj = pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return obj;
    }
}
